#include "port/datatype.h"
#include "onps_errors.h"
#include "port/sys_config.h"
#include "port/os_datatype.h"
#include "one_shot_timer.h"
#include "sys_timer.h"
#include "protocols.h"

#if SUPPORT_PPP
#include "scp.h"
#include "ppp/negotiation_storage.h"
#include "ppp/ppp.h"
#endif

#define SYMBOL_GLOBALS
#include "port/os_adapter.h"
#undef SYMBOL_GLOBALS

#if SUPPORT_PPP
//* 在此指定连接modem的串行口，以此作为tty终端进行ppp通讯
const CHAR *or_pszaTTY[PPP_NETLINK_NUM] = { "SCP3" };
const ST_DIAL_AUTH_INFO or_staDialAuth[PPP_NETLINK_NUM] = {
    { "4gnet", "card", "any_char" },  /* 注意ppp账户和密码尽量控制在20个字节以内，太长需要需要修改chap.c中send_response()函数的szData数组容量及 */
                                      /* pap.c中pap_send_auth_request()函数的ubaPacket数组的容量，确保其能够封装一个完整的响应报文              */
};
ST_PPPNEGORESULT o_staNegoResult[PPP_NETLINK_NUM] = {
    {
        { 0, PPP_MRU, ACCM_INIT,{ PPP_CHAP, 0x05 /* 对于CHAP协议来说，0-4未使用，0x05代表采用MD5算法 */ }, TRUE, TRUE, FALSE, FALSE },
        { IP_ADDR_INIT, DNS_ADDR_INIT, DNS_ADDR_INIT, IP_ADDR_INIT, MASK_INIT }, 0
    },

    /* 系统存在几路ppp链路，就在这里添加几路的协商初始值，如果不确定，可以直接将上面预定义的初始值直接复制过来即可 */
};
#endif

//* 用户自定义变量声明区
//* ===============================================================================================
#define THOSTIMERCOUNT_STK_SIZE	256
__align(8) OS_STK THOSTIMERCOUNT_STK[THOSTIMERCOUNT_STK_SIZE];

#if SUPPORT_PPP
#define THPPPHANDLER_STK_SIZE	384
__align(8) OS_STK THPPPHANDLER_STK[THPPPHANDLER_STK_SIZE];
#endif

static CHAR l_bTHMtxCurPIP = MTX_PIP_START_PRIO; 
//* ===============================================================================================

//* 协议栈内部工作线程列表
const static STCB_PSTACKTHREAD lr_stcbaPStackThread[] = {
	{ thread_one_shot_timer_count, (void *)0, (OS_STK *)&THOSTIMERCOUNT_STK[THOSTIMERCOUNT_STK_SIZE - 1], THOSTIMERCOUNT_PRIO },
#if SUPPORT_PPP
	{ thread_ppp_handler, (void *)0, (OS_STK *)&THPPPHANDLER_STK[THPPPHANDLER_STK_SIZE - 1], THPPPHANDLER_PRIO }, 
#endif	
}; 

//* 当前线程休眠指定的秒数，参数unSecs指定要休眠的秒数
void os_sleep_secs(UINT unSecs)
{
	OSTimeDlyHMSM(0, 0, unSecs, 0); 
}

//* 当前线程休眠指定的毫秒数，单位：毫秒 
void os_sleep_ms(UINT unMSecs)
{
    OSTimeDlyHMSM(0, 0, 0, unMSecs); 
}

//* 获取系统启动以来已运行的秒数（从0开始）
UINT os_get_system_secs(void)
{
	return GetElapsedSecs(); 
}

//* 获取系统启动以来已运行的毫秒数（从0开始）
UINT os_get_system_msecs(void)
{
    return GetElapsedMSecs();
}

void os_thread_onpstack_start(void *pvParam)
{
	pvParam = pvParam; //* 避免编译器警告
	
	//* 建立工作线程
	INT i; 
	for (i = 0; i < (INT)(sizeof(lr_stcbaPStackThread) / sizeof(STCB_PSTACKTHREAD)); i++)	
		OSTaskCreate(lr_stcbaPStackThread[i].pfunThread, lr_stcbaPStackThread[i].pvParam, lr_stcbaPStackThread[i].pstkTop, lr_stcbaPStackThread[i].ubPrio);
}

HMUTEX os_thread_mutex_init(void)
{
	OS_CPU_SR  cpu_sr = 0u;
	UCHAR ubErr; 
  CHAR bTHMtxCurPIP; 
	
	if(l_bTHMtxCurPIP <= 0) //* 如果预留的PIP用完了就无法再建立一个有效的互斥锁了
		return INVALID_HMUTEX;
  
  OS_ENTER_CRITICAL();
  bTHMtxCurPIP = l_bTHMtxCurPIP--; 
  OS_EXIT_CRITICAL();
  
	return OSMutexCreate(bTHMtxCurPIP, &ubErr);  
}

void os_thread_mutex_lock(HMUTEX hMutex)
{
	UCHAR ubErr; 
	OSMutexPend(hMutex, 0, &ubErr);
}

void os_thread_mutex_unlock(HMUTEX hMutex)
{
	OSMutexPost(hMutex);
}

void os_thread_mutex_uninit(HMUTEX hMutex)
{
	UCHAR ubErr;   
  OS_CPU_SR cpu_sr = 0;
  
  OS_ENTER_CRITICAL();
  l_bTHMtxCurPIP++; 
  OS_EXIT_CRITICAL();
  
	OSMutexDel(hMutex, OS_DEL_ALWAYS, &ubErr); 
}

HSEM os_thread_sem_init(UINT unInitVal, UINT unCount)
{
	unCount = unCount; //* 避免编译器警告	
	return OSSemCreate((USHORT)unInitVal);
}

void os_thread_sem_post(HSEM hSem)
{
	OSSemPost(hSem);
}

INT os_thread_sem_pend(HSEM hSem, INT nWaitSecs)
{
	UCHAR ubErr; 
	OSSemPend(hSem, (UINT)(nWaitSecs * OS_TICKS_PER_SEC), &ubErr);	
	if(OS_ERR_NONE == ubErr)
		return 0; 
  else if(OS_ERR_TIMEOUT == ubErr)
    return 1; 
	else
		return -1; 
}

void os_thread_sem_uninit(HSEM hSem)
{
	UCHAR ubErr; 
	OSSemDel(hSem, OS_DEL_ALWAYS, &ubErr); 
}

#if SUPPORT_PPP
HTTY os_open_tty(const CHAR *pszTTYName)
{
	pszTTYName = pszTTYName; //* 避免编译器警告
	
	SCP3Init(115200, DATABIT_8, STOPBITS_1, PARITYTP_NO, FLOWCTLTP_NO);	 
	return 0; 
}

void os_close_tty(HTTY hTTY)
{
	hTTY = hTTY; //* 避免编译器警告
}

INT os_tty_send(HTTY hTTY, UCHAR *pubData, INT nDataLen)
{
	hTTY = hTTY; //* 避免编译器警告
	return (INT)SCP3Send((INT8U *)pubData, (INT32U)nDataLen);
}

INT os_tty_recv(HTTY hTTY, UCHAR *pubRcvBuf, INT nRcvBufLen, INT nWaitSecs)
{
	hTTY = hTTY; //* 避免编译器警告
	return SCP3Recv((INT8U *)pubRcvBuf, (INT32U)nRcvBufLen, nWaitSecs); 
}

void os_modem_reset(HTTY hTTY)
{
#if SUPPORT_PRINTF
  printf("start reset modem...\r\n");
#endif 	
  SCP3ReInit(); 
  
	M4G_POWER_OFF();
  os_sleep_secs(3); 
	M4G_POWER_ON();
  os_sleep_secs(6); 
	
#if SUPPORT_PRINTF
  printf("reset modem succeeded.\r\n");
#endif 
}
#endif

